ATM location in New York

Context

State of New York

New York is a state located in the northeastern United States. New York was one of the original thirteen colonies that formed the United States. With more than 19 million residents in 2019,[6] it is the fourth most populous state. In order to distinguish the state from its city with the same name which is located within the state, it is sometimes referred to as New York State

https://en.wikipedia.org/wiki/New_York_(state)

Counties of New York

There are 62 counties in the state of New York. The most recent county formation in New York was in 1914, when Bronx County was created from the portions of New York City that had been annexed from Westchester County in the late 19th century and added to New York County. https://en.wikipedia.org/wiki/List_of_counties_in_New_York

Introduction/Business Problem

As a newcomer in finance industry, I think cash is has been, but still want to deploy new ATM structures inside NY state.

I'm looking for places where people are likely to withdraw money AND looking for places where people don't have yet any other good option to do so.

Using data science, I want to analyze ATM data, understand where the needs are. I want to understand how my competitors thinks about it. Given that, I want to find where to deploy my new pounds in order to bring the most value out of it.

Disclaimer

This work will be driven by data, more than any prior knowledge of surrounding context.

As a european who has only seen New york for a few days, I don't know much about how things are organized in US.

I've disovered the "state, county, city" organization during that course and know nothing about the finance industry.

Data I've found publicly available will drive my analysis, but I'm very aware that someone with closer relation to New-York and/or finance, will have different questions, understanding and expectations.

For the exercise I run into, understanding the context is king, all the machine-leaning in the world will not compensate for that, but yes this is an exercise.

Question 1: Where are the needs for new ATMs ?

In [1]:
import pandas as pd
import numpy as np
import folium
from geopy.geocoders import Nominatim
import seaborn as sns
from sklearn.cluster import KMeans

We will load a geojson files with new york counties and visualize the region

In [2]:
MAP_CENTER=[41, -73.125]
NY_COUNTIES_GEO="https://raw.githubusercontent.com/codeforamerica/click_that_hood/master/public/data/new-york-counties.geojson"
map_newyork = folium.Map(location = MAP_CENTER, zoom_start = 6)
map_newyork.choropleth(geo_data = NY_COUNTIES_GEO, 
                   fill_opacity=0.1,
                   line_opacity=1,
                   legend_name = "New York counties")
map_newyork
/home/cedric/miniconda3/lib/python3.7/site-packages/folium/folium.py:415: FutureWarning: The choropleth  method has been deprecated. Instead use the new Choropleth class, which has the same arguments. See the example notebook 'GeoJSON_and_choropleth' for how to do this.
  FutureWarning
Out[2]:
Make this Notebook Trusted to load map: File -> Trust Notebook

We can now load our ATM csv data, explore, clean and prepare it for our use case

In [3]:
df=pd.read_csv("Bank-Owned_ATM_Locations_in_New_York_State.csv")
df.head()
Out[3]:
Name of Institution Street Address City ZIP Code County Location 1
0 Abacus Federal Savings Bank 5518 8th Avenue Brooklyn 11220.0 Kings 5518 8th Avenue\nBrooklyn, NY 11220\n(40.63792...
1 Abacus Federal Savings Bank 36-30 Main Street Flushing 11354.0 Queens 36 30 Main Street\nFlushing, NY 11354
2 Abacus Federal Savings Bank 6-8 Bowery New York 10013.0 New York 6 8\nNew York, NY 10013\n(40.73733, -74.00504)
3 Abacus Federal Savings Bank 104-116 Nassau Street New York 10038.0 New York 104 116 Nassau Street\nNew York, NY 10038\n(40...
4 Access Federal Credit Union 74-76 Main Street Camden 13316.0 Oneida 74 76 Main Street\nCamden, NY 13316\n(43.33504...
  • Latitude and longitude information is present in this file however it is not normalized.
  • We extract those values from the "Location 1" field and store that in new columns
In [4]:
latlon=df["Location 1"].str.split("\n", n = 3, expand = True)[2].str.replace("(","").str.replace(")","").str.split(",",n=2,expand= True)
df["lat"]=latlon[0]
df["lon"]=latlon[1]
In [5]:
df.head()
Out[5]:
Name of Institution Street Address City ZIP Code County Location 1 lat lon
0 Abacus Federal Savings Bank 5518 8th Avenue Brooklyn 11220.0 Kings 5518 8th Avenue\nBrooklyn, NY 11220\n(40.63792... 40.637928 -74.007017
1 Abacus Federal Savings Bank 36-30 Main Street Flushing 11354.0 Queens 36 30 Main Street\nFlushing, NY 11354 None None
2 Abacus Federal Savings Bank 6-8 Bowery New York 10013.0 New York 6 8\nNew York, NY 10013\n(40.73733, -74.00504) 40.73733 -74.00504
3 Abacus Federal Savings Bank 104-116 Nassau Street New York 10038.0 New York 104 116 Nassau Street\nNew York, NY 10038\n(40... 40.710658 -74.007268
4 Access Federal Credit Union 74-76 Main Street Camden 13316.0 Oneida 74 76 Main Street\nCamden, NY 13316\n(43.33504... 43.335045 -75.748044
In [6]:
print(df.shape)
df.dropna(subset = ["lat","lon"]).shape
(5612, 8)
Out[6]:
(4688, 8)
In [7]:
df.dropna(subset = ["lat","lon"],inplace=True)

We have extracted latitude and longitude into new columns

  • We can use Nominatim to geocode address, this allows us to compare and validate the lat/lon extracted in the CSV with the one obtained from geocoder
  • We can also notice that a thousand entries are missing geo coordinates in our CSV data.
  • We could try to fill missing values using nominatim... but for our use case we can also drop those values for now
In [8]:
geolocator = Nominatim(user_agent="ny_explorer")
location = geolocator.geocode("5518 8th Avenue, Brooklyn, NY 11220")
location
Out[8]:
Location(5518, 8th Avenue, Sunset Park, South Battery, New York, Brooklyn, Kings County, New York, 11220, United States of America, (40.63804145, -74.00721315000001, 0.0))

We can now display all our ATMs on a map to understand how they are distributed across NY state

In [9]:
map_newyork = folium.Map(location = MAP_CENTER, zoom_start = 9)
for lat, lng, name, addr in zip(df['lat'], df['lon'], df['Name of Institution'], df['County']):
    if lat is not None and pd.notna(lat):
        label = '{}, {}'.format(name, addr)
        label = folium.Popup(label, parse_html=True)
        folium.CircleMarker(
            [lat, lng],
            radius=1,
            popup=label,
            color='blue',
            fill=False,
            fill_color='#3186cc',
            fill_opacity=0.4,
            parse_html=False).add_to(map_newyork)  
map_newyork
Out[9]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Exploring this point cloud we can confirm that ATM locations are all located around New-York state.

Some regions seems to have a much higher density of ATMs that other.

We can now combine the state geojson data with our ATM data into a single map

  • We count the number of ATMs per county and display that new value on the choropleth map
In [10]:
#County names used in geojson are not the same as the one we have in CSV
#we need to adapt our dataset
#we create the column "County_idx" to be able to join geodata
NY_COUNTIES_GEO_KEY="feature.properties.name"
df["County_idx"]=df["County"].map(str)+" County"
df["County_idx"]=df["County_idx"].replace('Montogomery County','Montgomery County')
count_by_county= df["County_idx"].value_counts().reset_index();
count_by_county.head()
Out[10]:
index County_idx
0 New York County 626
1 Nassau County 492
2 Suffolk County 425
3 Kings County 373
4 Westchester County 308
In [11]:
map_newyork = folium.Map(location = MAP_CENTER, zoom_start = 6)
map_newyork.choropleth(geo_data = NY_COUNTIES_GEO, 
                   key_on = NY_COUNTIES_GEO_KEY,
                   data =count_by_county, columns = ["index", "County_idx"],
                   fill_opacity=0.9,
                   line_opacity=1,
                   legend_name = "ATM density per county")
# add markers to map
for lat, lng, name, addr in zip(df['lat'], df['lon'], df['Name of Institution'], df['County_idx']):
    if lat is not None and pd.notna(lat):
        label = '{}, {}'.format(name, addr)
        label = folium.Popup(label, parse_html=True)
        folium.CircleMarker(
            [lat, lng],
            radius=2,
            popup=label,
            color='red',
            fill=True,
            fill_color='#3186cc',
            opacity=0.1,
            parse_html=False).add_to(map_newyork)  
map_newyork
/home/cedric/miniconda3/lib/python3.7/site-packages/folium/folium.py:415: FutureWarning: The choropleth  method has been deprecated. Instead use the new Choropleth class, which has the same arguments. See the example notebook 'GeoJSON_and_choropleth' for how to do this.
  FutureWarning
Out[11]:
Make this Notebook Trusted to load map: File -> Trust Notebook
  • Many counties have low number of ATMs (in white).
  • Manathan get it's own class with an unusally high amount of ATMs (deep blue)

  • The area of a county is probably not relevant for explaining ATM location, many large counties have low number of ATMs.

  • Counties with high population should have high number of ATMs.
  • That's our next intuition and we will validate that with data.

To validate our last assumption, we load a new dataset and assign to each county a value for population

In [12]:
pop = pd.read_html("https://www.newyork-demographics.com/counties_by_population",
                          header=0,
                          attrs={"class":"ranklist"})[0]
pop.drop("Rank",axis=1,inplace=True)
pop.drop(62,axis=0,inplace=True)
pop["Population"]=pd.to_numeric(pop["Population"], errors='raise')
pop.head()
Out[12]:
County Population
0 Kings County 2600747
1 Queens County 2298513
2 New York County 1632480
3 Suffolk County 1487901
4 Bronx County 1437872
  • We merge the new population data into our main dataframe
In [13]:
df.shape
Out[13]:
(4688, 9)
In [14]:
df.merge(pop, left_on='County_idx', right_on='County').shape
Out[14]:
(4688, 11)
In [15]:
atm_count=df["County_idx"].value_counts().reset_index()
atm_count.rename(columns={'County_idx': 'ATM_count',"index":"County"},inplace=True)
atm_count
dd=atm_count.merge(pop, left_on='County', right_on='County')
dd
Out[15]:
County ATM_count Population
0 New York County 626 1632480
1 Nassau County 492 1356564
2 Suffolk County 425 1487901
3 Kings County 373 2600747
4 Westchester County 308 968815
... ... ... ...
57 Lewis County 8 26719
58 Orleans County 7 41175
59 Montgomery County 7 49426
60 Schuyler County 6 17992
61 Hamilton County 1 4575

62 rows × 3 columns

We suspect a high correlation between the number of ATM in a county and it's population

  • one way to verify this is to plot and compare, the frequency distribution for both features.
In [16]:
sns.distplot(dd["ATM_count"]).set(xlim=(0));
In [17]:
sns.distplot(dd["Population"]).set(xlim=(0));

It seams pretty clear from those charts that both features have a very similar distribution.

  • Combining those metrics to get the number of ATM per habitant is probably a good idea.
In [18]:
dd["ATM_per_hab"]=dd["ATM_count"]/dd["Population"]
sns.distplot(dd["ATM_per_hab"]);

The distribution we observe here is very close to a gaussian.

In [19]:
1/(dd["ATM_per_hab"].mean())
Out[19]:
3527.6218695204057
In [20]:
from sklearn.linear_model import LinearRegression
def test_lin_reg(data):
    sns.regplot(x="Population", y="ATM_count", data=data)
    X = np.array(data["Population"]).reshape(-1, 1)
    y = data["ATM_count"]
    reg = LinearRegression().fit(X, y)
    print("score=",reg.score(X, y))
    print("slope=",reg.coef_[0])
    print("one ATM per {} habitants".format(round(1/reg.coef_[0])))
    data["std_err"]=(data["ATM_count"]-reg.predict(data["Population"].to_numpy().reshape(-1, 1)))**2
    print("outliers",data.sort_values("std_err").tail())
In [21]:
test_lin_reg(dd)
score= 0.629892201249413
slope= 0.0001806332109059001
one ATM per 5536.0 habitants
outliers              County  ATM_count  Population  ATM_per_hab        std_err
8      Bronx County        159     1437872     0.000111   14204.629349
2    Suffolk County        425     1487901     0.000286   18983.307865
1     Nassau County        492     1356564     0.000363   52213.963536
0   New York County        626     1632480     0.000383   97758.874747
11    Queens County         91     2298513     0.000040  117404.583771
In [22]:
test_lin_reg(pd.DataFrame(dd.loc[dd["County"]!="Queens County"]))
score= 0.790829862100781
slope= 0.00022887350524034925
one ATM per 4369.0 habitants
outliers                County  ATM_count  Population  ATM_per_hab       std_err
4  Westchester County        308      968815     0.000318   5759.003957
1       Nassau County        492     1356564     0.000363  29289.799381
8        Bronx County        159     1437872     0.000111  32568.200283
3        Kings County        373     2600747     0.000143  54111.085355
0     New York County        626     1632480     0.000383  58560.499133

business rule of thumb:

  • 1 ATM for every 4400 habitants on average in every county

Counties on the low tail are where we should build new ATMs

In [23]:
dd.nsmallest(5,"ATM_per_hab")
Out[23]:
County ATM_count Population ATM_per_hab std_err
11 Queens County 91 2298513 0.000040 117404.583771
50 Putnam County 10 99070 0.000101 694.378974
8 Bronx County 159 1437872 0.000111 14204.629349
59 Montgomery County 7 49426 0.000142 415.495897
3 Kings County 373 2600747 0.000143 13279.570950

On the opposite side those are counties with 'too many ATMs' according to our population rule

In [24]:
dd.nlargest(5,"ATM_per_hab")
Out[24]:
County ATM_count Population ATM_per_hab std_err
25 Warren County 33 64480 0.000512 8.392790
40 Essex County 18 37751 0.000477 52.923060
38 Allegany County 21 47025 0.000447 35.402692
9 Albany County 137 307426 0.000446 3970.627472
49 Schoharie County 13 31364 0.000414 123.679297

Next iteration, time to load more data and put things in perspective.

So far we've found a very strong correlation between county population and number of ATMs.

"Queens County", "Putnam County" needs more ATM, and "Warren County" or "Essex County" have too much.

To validate those findings, we would need to improve our data collection, use geocoder on ATMs without location data and find additionnal ATM data sources.

Population is definitely a major feature, but we also need to take more factors into consideration, before investing in new ATMs

  • Wealth, crime, mobility, something else ?
  • I don't know... I will try wealth, this is exploratory

We will look at median household income for each county

  • can we observe higher ATM density in wealthier regions ?
In [25]:
wealth = pd.read_html("https://en.wikipedia.org/wiki/List_of_New_York_locations_by_per_capita_income",
                          header=0,
                          attrs={"class":"wikitable sortable"})[0]
wealth.drop("Rank",axis=1,inplace=True)
wealth["County"]=wealth["County"].apply(lambda s: s if(s.endswith("County")) else s+" County" )
wealth["Medianhouseholdincome"]=pd.to_numeric(wealth["Medianhouseholdincome"].str.replace("$","").str.replace(",",""), errors='raise')
In [26]:
ddd=dd.merge(wealth, left_on='County', right_on='County')
In [27]:
ddd.head()
Out[27]:
County ATM_count Population_x ATM_per_hab std_err Per capitaincome Medianhouseholdincome Medianfamilyincome Population_y Number ofhouseholds
0 New York County 626 1632480 0.000383 97758.874747 $111,386 64971 $75,629 1585873 763846
1 Nassau County 492 1356564 0.000363 52213.963536 $41,387 93613 $107,934 1339532 448528
2 Suffolk County 425 1487901 0.000286 18983.307865 $35,755 84506 $96,220 1493350 499922
3 Kings County 373 2600747 0.000143 13279.570950 $23,605 43567 $48,777 2504700 916856
4 Westchester County 308 968815 0.000318 13120.350019 $73,159 79619 $100,863 949113 347232
In [28]:
ddd.nlargest(5,"Medianhouseholdincome")
Out[28]:
County ATM_count Population_x ATM_per_hab std_err Per capitaincome Medianhouseholdincome Medianfamilyincome Population_y Number ofhouseholds
1 Nassau County 492 1356564 0.000363 52213.963536 $41,387 93613 $107,934 1339532 448528
50 Putnam County 10 99070 0.000101 694.378974 $37,915 89218 $101,576 99710 35041
2 Suffolk County 425 1487901 0.000286 18983.307865 $35,755 84506 $96,220 1493350 499922
17 Rockland County 57 323686 0.000176 396.972984 $34,304 82534 $96,836 311687 99242
4 Westchester County 308 968815 0.000318 13120.350019 $73,159 79619 $100,863 949113 347232
In [29]:
ddd.nsmallest(5,"Medianhouseholdincome")
Out[29]:
County ATM_count Population_x ATM_per_hab std_err Per capitaincome Medianhouseholdincome Medianfamilyincome Population_y Number ofhouseholds
8 Bronx County 159 1437872 0.000111 14204.629349 $17,575 34264 $38,431 1385108 483449
22 Chautauqua County 39 129656 0.000301 8.270910 $21,033 40639 $51,031 134905 54244
38 Allegany County 21 47025 0.000447 35.402692 $20,058 41305 $49,864 48946 18208
46 Franklin County 13 50692 0.000256 213.522178 $19,807 42050 $50,816 51599 19054
29 St. Lawrence County 29 109558 0.000265 85.480245 $20,143 42303 $50,384 111944 41605
In [30]:
sns.scatterplot(ddd["Medianhouseholdincome"],ddd["ATM_per_hab"])
Out[30]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f7f6f930410>

Somehow disapointing, This looks like totally uncorellated

Median household income doesn't seem to explain why some counties have more or less ATMs than other.

Conclusion of that first step and summary of findings

When it comes to chosing a location for new ATM:

  • consider density of population
  • wealth seems irrelevant
  • also collect more data and analyze more potential features, such as crimes, cashless habits, ...

Limitations on that approach:

  • we only deal with location of ATMs and no performance indication
  • we would like to know which one works best (trxs/data, amount/day), but those data are probaly kept secret
  • might be safe to assume that long-time underperforming ATMs have been dismantled

Question 2 Competitors analysis

In competitor analysis we will switch focus to focus on institution rather than county.

We will try to discover patterns in ATM location for each institution, and understand the strategy they use to choose their ATM locations.

  • Does institution-A place ATM location systematically close to restaurant ?
  • May be instituion-B ATMs are always placed close transportation service ?

  • We will use foursquare API to gather data about suroundings.

  • Apply clustering on venues and categories.

If we can understand the strategies that our competitors are using this will give us a great competitive avantage for the future.

We will

  • use foursquare API to gather data about ATM locations surounding.
  • use clustering algorith on venue data

To avoid going over quotas on foursquare api

  • we will not use our full dataset but use some random samples instead
In [31]:
institution=df.groupby(["Name of Institution"])["County"].nunique()\
.sort_values(ascending=False).head(10).keys().to_list()
institution
Out[31]:
['Key Bank, National Association',
 'Manufacturers and Traders Trust Company',
 'Community Bank, N.A.',
 'NBT Bank, National Association',
 'Bank of America N.A. GA1-006-15-40',
 'Citizens Bank',
 'TD Bank N.A.',
 'JPMorgan Chase Bank, National Association',
 'Five Star Bank',
 'Trustco Bank N.A. CTF']
  • We want to identify patterns about the institution rather than counties.
  • We chose to focus only on biggest 10 institutions that are present in many counties,
In [32]:
df1 = df.loc[df["Name of Institution"].isin(institution)]\
.groupby(["Name of Institution","County"], group_keys=False)
t=df1.apply(lambda df: df.sample(1)).groupby("Name of Institution").apply(lambda df:df.sample(5))
t
Out[32]:
Name of Institution Street Address City ZIP Code County Location 1 lat lon County_idx
Name of Institution
Bank of America N.A. GA1-006-15-40 509 Bank of America N.A. GA1-006-15-40 1 East Avenue Rochester 14638.0 Monroe 1 East Avenue\nRochester, NY 14638\n(43.157458... 43.157458 -77.603956 Monroe County
282 Bank of America N.A. GA1-006-15-40 1415 Avenue Z Brooklyn 11235.0 Kings 1415 Avenue\nBrooklyn, NY 11235\n(40.59004, -7... 40.59004 -73.9551 Kings County
261 Bank of America N.A. GA1-006-15-40 100 Main Street Batavia 14020.0 Genesee 100 Main Street\nBatavia, NY 14020\n(42.997411... 42.997411 -78.182211 Genesee County
538 Bank of America N.A. GA1-006-15-40 2196 Forest Avenue Staten Island 10303.0 Richmond 2196 Forest Avenue\nStaten Island, NY 10303\n(... 40.626735 -74.162713 Richmond County
499 Bank of America N.A. GA1-006-15-40 231 Beach 20th Street Queens 11691.0 Queens 231 Beach 20th Street\nQueens, NY 11691\n(40.5... 40.596098 -73.754121 Queens County
Citizens Bank 1456 Citizens Bank 49 Dix Avenue Queensbury 12801.0 Warren 49 Dix Avenue\nQueensbury, NY 12801\n(43.31748... 43.317486 -73.63825 Warren County
1421 Citizens Bank 6545 Transit Road East Amherst 14051.0 Erie 6545 Transit Road\nEast Amherst, NY 14051\n(43... 43.027293 -78.696927 Erie County
1498 Citizens Bank 2371 Central Park Avenue Yonkers 10710.0 Westchester 2371 Central Park Avenue\nYonkers, NY 10710\n(... 40.979184 -73.830512 Westchester County
1435 Citizens Bank 17 South Market Johnstown 12095.0 Fulton 17 South Market\nJohnstown, NY 12095\n(43.0057... 43.005701 -74.372667 Fulton County
1443 Citizens Bank 265 Osborne Road Loudonville 12211.0 Albany 265 Osborne Road\nLoudonville, NY 12211\n(42.7... 42.706837 -73.775497 Albany County
Community Bank, N.A. 1619 Community Bank, N.A. 18 South Broad Street Norwich 13815.0 Chenango 18 South Broad Street\nNorwich, NY 13815\n(42.... 42.530529 -75.523722 Chenango County
1573 Community Bank, N.A. 300 West Water Street Elmira 14901.0 Chemung 300 West Water Street\nElmira, NY 14901\n(42.0... 42.087091 -76.810154 Chemung County
1570 Community Bank, N.A. 345 Central Avenue Dunkirk 14048.0 Chautauqua 345 Central Avenue\nDunkirk, NY 14048\n(42.483... 42.483392 -79.334524 Chautauqua County
1551 Community Bank, N.A. 2516 West Main Street Cato 13033.0 Cayuga 2516 West Main Street\nCato, NY 13033\n(43.167... 43.167941 -76.573886 Cayuga County
1676 Community Bank, N.A. 401 North Franklin Street Watkins Glen 14891.0 Schuyler 401 North Franklin Street\nWatkins Glen, NY 14... 42.380389 -76.873365 Schuyler County
Five Star Bank 2058 Five Star Bank 25 Shethar Street Hammondsport 14840.0 Steuben 25 Shethar Street\nHammondsport, NY 14840\n(42... 42.409531 -77.221727 Steuben County
2027 Five Star Bank 102 North Main Street Albion 14411.0 Orleans 102 North Main Street\nAlbion, NY 14411\n(43.2... 43.248174 -78.193706 Orleans County
2087 Five Star Bank 545 Broad Street Salamanca 14779.0 Cattaraugus 545 Broad Street\nSalamanca, NY 14779\n(42.158... 42.158167 -78.735338 Cattaraugus County
2068 Five Star Bank 184 South Main Street Naples 14512.0 Ontario 184 South Main Street\nNaples, NY 14512\n(42.6... 42.610533 -77.406583 Ontario County
2063 Five Star Bank 284 East Fairmount Avenue Lakewood 14750.0 Chautauqua 284 East Fairmount Avenue\nLakewood, NY 14750\... 42.098293 -79.306883 Chautauqua County
JPMorgan Chase Bank, National Association 2877 JPMorgan Chase Bank, National Association 1324 York Avenue New York 10021.0 New York 1324 York Avenue\nNew York, NY 10021\n(40.7660... 40.766011 -73.954361 New York County
2745 JPMorgan Chase Bank, National Association 256 Plaza Road, Kingston Plaza Kingston 12401.0 Ulster 256 Plaza Road\nKingston, NY 12401\n(41.93688,... 41.93688 -74.018182 Ulster County
2636 JPMorgan Chase Bank, National Association 36 Broadway & Quaker Avenue Cornwall 12518.0 Orange 36 Broadway &amp; Quaker Avenue\nCornwall, NY ... 41.434367 -74.03935 Orange County
2741 JPMorgan Chase Bank, National Association 17562 Hillside Avenue Jamaica 11432.0 Queens 17562 Hillside Avenue\nJamaica, NY 11432\n(40.... 40.712113 -73.785866 Queens County
2604 JPMorgan Chase Bank, National Association 5101 4th Avenue Brooklyn 11220.0 Kings 5101 4th Avenue\nBrooklyn, NY 11220\n(40.64575... 40.645756 -74.013211 Kings County
Key Bank, National Association 3358 Key Bank, National Association 41 Kellogg Road New Hartford 13413.0 Oneida 41 Kellogg Road\nNew Hartford, NY 13413\n(43.0... 43.054988 -75.277685 Oneida County
3387 Key Bank, National Association 1609 Main Street Pleasant Valley 12569.0 Dutchess 1609 Main Street\nPleasant Valley, NY 12569\n(... 41.744332 -73.823922 Dutchess County
3385 Key Bank, National Association 5063 U.S. Avenue Plattsburgh 12901.0 Clinton 5063 U S Avenue\nPlattsburgh, NY 12901\n(44.68... 44.682269 -73.448322 Clinton County
3311 Key Bank, National Association 300 North Tioga Street Ithaca 14850.0 Tompkins 300 North Tioga Street\nIthaca, NY 14850\n(42.... 42.441595 -76.496935 Tompkins County
3245 Key Bank, National Association 245 West Bridge Street Catskill 12414.0 Greene 245 West Bridge Street\nCatskill, NY 12414\n(4... 42.214611 -73.881207 Greene County
Manufacturers and Traders Trust Company 3608 Manufacturers and Traders Trust Company 307 Main Street Goshen 10924.0 Orange 307 Main Street\nGoshen, NY 10924\n(41.407615,... 41.407615 -74.315723 Orange County
3729 Manufacturers and Traders Trust Company 25 Hill Street Southampton 11968.0 Suffolk 25 Hill Street\nSouthampton, NY 11968\n(40.883... 40.883577 -72.394183 Suffolk County
3646 Manufacturers and Traders Trust Company 118 Walnut Street Lockport 14094.0 Niagara 118 Walnut Street\nLockport, NY 14094\n(43.168... 43.168908 -78.691605 Niagara County
3547 Manufacturers and Traders Trust Company 1300 Jefferson Avenue Buffalo 14208.0 Erie 1300 Jefferson Avenue\nBuffalo, NY 14208\n(42.... 42.910538 -78.853985 Erie County
3510 Manufacturers and Traders Trust Company 911 Central Avenue Albany 12206.0 Albany 911 Central Avenue\nAlbany, NY 12206\n(42.6814... 42.681478 -73.791629 Albany County
NBT Bank, National Association 3899 NBT Bank, National Association 9 Clifton Country Road Clifton Park 12065.0 Saratoga 9 Clifton Country Road\nClifton Park, NY 12065... 42.860121 -73.780919 Saratoga County
3976 NBT Bank, National Association 105 MAIN STREET SHARON SPRINGS 13459.0 Schoharie 105 MAIN STREET\nSHARON SPRINGS, NY 13459\n(42... 42.78969 -74.621974 Schoharie County
3963 NBT Bank, National Association 60 Margaret St Plattsburgh 12901.0 Clinton 60 Margaret St\nPlattsburgh, NY 12901\n(44.697... 44.697133 -73.453059 Clinton County
3924 NBT Bank, National Association 5 New Karner Road -- Route 155 Guilderland 12084.0 Albany 5 New Karner Road -- Route\nGuilderland, NY 12... 42.698322 -73.887311 Albany County
3928 NBT Bank, National Association 1 Madison St Hamilton 13346.0 Madison 1 Madison St\nHamilton, NY 13346\n(42.827146, ... 42.827146 -75.544306 Madison County
TD Bank N.A. 4977 TD Bank N.A. 411 Washington Avenue Kingston 12401.0 Ulster 411 Washington Avenue\nKingston, NY 12401\n(41... 41.935842 -74.025227 Ulster County
5001 TD Bank N.A. 540-550 Jericho Turnpike Mineola 11501.0 Nassau 540 550 Jericho Turnpike\nMineola, NY 11501\n(... 40.743894 -73.656909 Nassau County
5025 TD Bank N.A. 919 Second Avenue New York 10017.0 New York 919 Second Avenue\nNew York, NY 10017\n(40.754... 40.754067 -73.96911 New York County
5003 TD Bank N.A. 463 Broadway Monticello 12701.0 Sullivan 463 Broadway\nMonticello, NY 12701\n(41.655347... 41.655347 -74.688423 Sullivan County
5009 TD Bank N.A. 39 North Plank Road Newburgh 12550.0 Orange 39 North Plank Road\nNewburgh, NY 12550\n(41.5... 41.522404 -74.027798 Orange County
Trustco Bank N.A. CTF 5318 Trustco Bank N.A. CTF 7391 South Broadway (Route 9) Red Hook 12571.0 Dutchess 7391 South Broadway Route\nRed Hook, NY 12571\... 41.990657 -73.879928 Dutchess County
5310 Trustco Bank N.A. CTF 20 Squadron Boulevard New City 10956.0 Rockland 20 Squadron Boulevard\nNew City, NY 10956\n(41... 41.157516 -73.983229 Rockland County
5309 Trustco Bank N.A. CTF 222 East Main Street Mount Kisco 10549.0 Westchester 222 East Main Street\nMount Kisco, NY 10549\n(... 41.203078 -73.72656 Westchester County
5275 Trustco Bank N.A. CTF 345 Main Street Catskill 12414.0 Greene 345 Main Street\nCatskill, NY 12414\n(42.21800... 42.218005 -73.865062 Greene County
5279 Trustco Bank N.A. CTF 1541 CRESCENT ROAD CLIFTON PARK 12065.0 Saratoga 1541 CRESCENT ROAD\nCLIFTON PARK, NY 12065\n(4... 42.819052 -73.773947 Saratoga County

We have selected 5 random ATMs for each institution and additionnaly we choose them so that they are not all located inside the same county.

In [33]:
t["Name of Institution"].value_counts()
Out[33]:
Five Star Bank                               5
Manufacturers and Traders Trust Company      5
JPMorgan Chase Bank, National Association    5
Key Bank, National Association               5
Trustco Bank N.A. CTF                        5
Community Bank, N.A.                         5
TD Bank N.A.                                 5
Bank of America N.A. GA1-006-15-40           5
NBT Bank, National Association               5
Citizens Bank                                5
Name: Name of Institution, dtype: int64

We visualize those selected ATM on a map

In [34]:
import matplotlib.cm as cm
import matplotlib.colors as colors
map_newyork = folium.Map(location=MAP_CENTER, zoom_start=6)
rainbow = cm.rainbow(np.linspace(0, 1, len(institution)))
rainbowm = dict(zip(institution,rainbow))
for lat, lng, name, addr in zip(t['lat'], t['lon'], t['Name of Institution'], t['County_idx']):
    if lat is not None and pd.notna(lat):
        label = '{}, {}'.format(name, addr)
        label = folium.Popup(label, parse_html=True)
        folium.CircleMarker(
            [lat, lng],
            radius=5,
            popup=label,
            color=colors.rgb2hex(rainbowm.get(name,[0,0,0])),
            fill=True,
            fill_color=colors.rgb2hex(rainbowm.get(name,[0,0,0])),
            fill_opacity=1,
            parse_html=False).add_to(map_newyork)  
map_newyork
Out[34]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [35]:
import requests
import requests_cache
import time

requests_cache.install_cache('foursquare_cache', backend='sqlite', expire_after=60*60*24*14)

CLIENT_ID = 'VEOT5G4R5G5NCEH1EIHTGGWJ4PLQLZNINFK3A10IWD3DRH11' # your Foursquare ID
CLIENT_SECRET = '02QISYXURM1GZFWOTNV4ET4LWXEGS2F22EQHU1MUU50Q0I05' # your Foursquare Secret
VERSION = '20180605' # Foursquare API version

def explore_url (lat,lon,radius, limit):
    return 'https://api.foursquare.com/v2/venues/explore?&client_id={}&client_secret={}&v={}&ll={},{}&radius={}&limit={}'.format(
    CLIENT_ID, 
    CLIENT_SECRET, 
    VERSION, 
    lat, 
    lon, 
    radius, 
    limit)

def request(url):
    now = time.ctime(int(time.time()))
    response = requests.get(url)
    print("Time: {0} / Used Cache: {1}".format(now, response.from_cache))
    return response.json()
  • we use requests_cache to make sure we don't send the same request many times and go over quotas
In [47]:
def getNearbyVenues(atm_id, latitudes, longitudes, radius=500, limit=1000):
    venues_list=[]
    for idx, lat, lng in zip(atm_id, latitudes, longitudes):
        url=explore_url(lat, lng, radius, limit)    
        results = request(url)
        results=results["response"]['groups'][0]['items']
        venues_list.append([(
            idx, 
            v['venue']['categories'][0]['name']) for v in results])

    nearby_venues = pd.DataFrame([item for venue_list in venues_list for item in venue_list])
    nearby_venues.columns = ['atm_idx','category'] 
    return nearby_venues;
In [48]:
def cat_df(i):
    sample_atms=t.loc[i]
    r=getNearbyVenues(atm_id=sample_atms.index,latitudes=sample_atms['lat'],longitudes=sample_atms['lon'])
    tmp=r.groupby("category").count().reset_index()
    tmp["institution"]=i
    tmp.rename(columns={"atm_idx":"count"},inplace=True)
    return tmp.sort_values("count",ascending=False)
    
all_categories=pd.concat([cat_df(i) for i in institution],ignore_index=True)
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
Time: Sun Jun 28 13:53:49 2020 / Used Cache: True
In [52]:
all_categories.sort_values("count",ascending=False)
Out[52]:
category count institution
484 Pizza Place 13 JPMorgan Chase Bank, National Association
386 American Restaurant 12 TD Bank N.A.
0 Pharmacy 9 Key Bank, National Association
139 Pizza Place 9 Community Bank, N.A.
486 Coffee Shop 8 JPMorgan Chase Bank, National Association
... ... ... ...
300 Paper / Office Supplies Store 1 Bank of America N.A. GA1-006-15-40
299 Wings Joint 1 Bank of America N.A. GA1-006-15-40
298 Thrift / Vintage Store 1 Bank of America N.A. GA1-006-15-40
297 Theater 1 Bank of America N.A. GA1-006-15-40
668 Wine Bar 1 Trustco Bank N.A. CTF

669 rows × 3 columns

for the 5 selected ATMs that are owned by JPMorgan Chase Bank we have found 13 pizza places in total in the surroundings.

We can try to visualize those categories using a pivot table

In [53]:
pd.pivot_table(all_categories,
               values='count', 
               index=['category'],
               columns=['institution'],
               aggfunc=np.sum, 
               fill_value=0)
Out[53]:
institution Bank of America N.A. GA1-006-15-40 Citizens Bank Community Bank, N.A. Five Star Bank JPMorgan Chase Bank, National Association Key Bank, National Association Manufacturers and Traders Trust Company NBT Bank, National Association TD Bank N.A. Trustco Bank N.A. CTF
category
Accessories Store 0 0 0 1 0 0 0 0 0 0
Afghan Restaurant 0 0 0 0 1 0 0 0 0 0
African Restaurant 0 0 0 0 0 0 0 0 0 1
American Restaurant 7 0 6 5 6 5 3 5 12 4
Art Gallery 1 0 0 0 1 0 0 0 0 0
... ... ... ... ... ... ... ... ... ... ...
Wine Shop 0 2 0 0 2 1 0 0 1 0
Wings Joint 1 0 0 0 0 0 0 0 0 0
Women's Store 0 1 0 1 1 0 2 2 0 0
Yoga Studio 1 1 0 0 1 1 0 0 0 0
Zoo Exhibit 0 0 0 0 0 0 0 0 1 0

220 rows × 10 columns

The granularity of categories in foursquare response is way to low, we don't need that level of detail.

Using the foursquare category endpoint we can build a mapping and reduce the dimension of the category feature.

GET https://api.foursquare.com/v2/venues/categories

In [54]:
categories=requests.get('https://api.foursquare.com/v2/venues/categories?&client_id={}&client_secret={}&v={}'\
                        .format(CLIENT_ID,CLIENT_SECRET,VERSION))

[i["name"] for i in categories.json()["response"]["categories"]]
Out[54]:
['Arts & Entertainment',
 'College & University',
 'Event',
 'Food',
 'Nightlife Spot',
 'Outdoors & Recreation',
 'Professional & Other Places',
 'Residence',
 'Shop & Service',
 'Travel & Transport']

The top 10 parent categories are great for our use case.

We can use a recursive function to walk though the category tree and build a mapping that convert to parent category

In [55]:
category_mapping={}
        
def load_children(parent,childs):        
    for child in childs:
        if(child["name"] in category_mapping):
            raise Exception('duplicate', child["name"])
        category_mapping[child["name"]]=parent
        if child["categories"]:
            load_children(parent,child["categories"])

for i in categories.json()["response"]["categories"]:
    load_children(i["name"],i["categories"])

category_mapping
Out[55]:
{'Amphitheater': 'Arts & Entertainment',
 'Aquarium': 'Arts & Entertainment',
 'Arcade': 'Arts & Entertainment',
 'Art Gallery': 'Arts & Entertainment',
 'Bowling Alley': 'Arts & Entertainment',
 'Casino': 'Arts & Entertainment',
 'Circus': 'Arts & Entertainment',
 'Comedy Club': 'Arts & Entertainment',
 'Concert Hall': 'Arts & Entertainment',
 'Country Dance Club': 'Arts & Entertainment',
 'Disc Golf': 'Arts & Entertainment',
 'Exhibit': 'Arts & Entertainment',
 'General Entertainment': 'Arts & Entertainment',
 'Go Kart Track': 'Arts & Entertainment',
 'Historic Site': 'Arts & Entertainment',
 'Karaoke Box': 'Arts & Entertainment',
 'Laser Tag': 'Arts & Entertainment',
 'Memorial Site': 'Arts & Entertainment',
 'Mini Golf': 'Arts & Entertainment',
 'Movie Theater': 'Arts & Entertainment',
 'Drive-in Theater': 'Arts & Entertainment',
 'Indie Movie Theater': 'Arts & Entertainment',
 'Multiplex': 'Arts & Entertainment',
 'Museum': 'Arts & Entertainment',
 'Art Museum': 'Arts & Entertainment',
 'Erotic Museum': 'Arts & Entertainment',
 'History Museum': 'Arts & Entertainment',
 'Planetarium': 'Arts & Entertainment',
 'Science Museum': 'Arts & Entertainment',
 'Music Venue': 'Arts & Entertainment',
 'Jazz Club': 'Arts & Entertainment',
 'Piano Bar': 'Arts & Entertainment',
 'Rock Club': 'Arts & Entertainment',
 'Pachinko Parlor': 'Arts & Entertainment',
 'Performing Arts Venue': 'Arts & Entertainment',
 'Dance Studio': 'Arts & Entertainment',
 'Indie Theater': 'Arts & Entertainment',
 'Opera House': 'Arts & Entertainment',
 'Theater': 'Arts & Entertainment',
 'Pool Hall': 'Arts & Entertainment',
 'Public Art': 'Arts & Entertainment',
 'Outdoor Sculpture': 'Arts & Entertainment',
 'Street Art': 'Arts & Entertainment',
 'Racecourse': 'Arts & Entertainment',
 'Racetrack': 'Arts & Entertainment',
 'Roller Rink': 'Arts & Entertainment',
 'Salsa Club': 'Arts & Entertainment',
 'Samba School': 'Arts & Entertainment',
 'Stadium': 'Arts & Entertainment',
 'Baseball Stadium': 'Arts & Entertainment',
 'Basketball Stadium': 'Arts & Entertainment',
 'Cricket Ground': 'Arts & Entertainment',
 'Football Stadium': 'Arts & Entertainment',
 'Hockey Arena': 'Arts & Entertainment',
 'Rugby Stadium': 'Arts & Entertainment',
 'Soccer Stadium': 'Arts & Entertainment',
 'Tennis Stadium': 'Arts & Entertainment',
 'Track Stadium': 'Arts & Entertainment',
 'Theme Park': 'Arts & Entertainment',
 'Theme Park Ride / Attraction': 'Arts & Entertainment',
 'Tour Provider': 'Arts & Entertainment',
 'Water Park': 'Arts & Entertainment',
 'Zoo': 'Arts & Entertainment',
 'Zoo Exhibit': 'Arts & Entertainment',
 'College Academic Building': 'College & University',
 'College Arts Building': 'College & University',
 'College Communications Building': 'College & University',
 'College Engineering Building': 'College & University',
 'College History Building': 'College & University',
 'College Math Building': 'College & University',
 'College Science Building': 'College & University',
 'College Technology Building': 'College & University',
 'College Administrative Building': 'College & University',
 'College Auditorium': 'College & University',
 'College Bookstore': 'College & University',
 'College Cafeteria': 'College & University',
 'College Classroom': 'College & University',
 'College Gym': 'College & University',
 'College Lab': 'College & University',
 'College Library': 'College & University',
 'College Quad': 'College & University',
 'College Rec Center': 'College & University',
 'College Residence Hall': 'College & University',
 'College Stadium': 'College & University',
 'College Baseball Diamond': 'College & University',
 'College Basketball Court': 'College & University',
 'College Cricket Pitch': 'College & University',
 'College Football Field': 'College & University',
 'College Hockey Rink': 'College & University',
 'College Soccer Field': 'College & University',
 'College Tennis Court': 'College & University',
 'College Track': 'College & University',
 'College Theater': 'College & University',
 'Community College': 'College & University',
 'Fraternity House': 'College & University',
 'General College & University': 'College & University',
 'Law School': 'College & University',
 'Medical School': 'College & University',
 'Sorority House': 'College & University',
 'Student Center': 'College & University',
 'Trade School': 'College & University',
 'University': 'College & University',
 'Christmas Market': 'Event',
 'Conference': 'Event',
 'Convention': 'Event',
 'Festival': 'Event',
 'Line / Queue': 'Event',
 'Music Festival': 'Event',
 'Other Event': 'Event',
 'Parade': 'Event',
 'Sporting Event': 'Event',
 'Stoop Sale': 'Event',
 'Street Fair': 'Event',
 'Trade Fair': 'Event',
 'Afghan Restaurant': 'Food',
 'African Restaurant': 'Food',
 'Ethiopian Restaurant': 'Food',
 'American Restaurant': 'Food',
 'New American Restaurant': 'Food',
 'Asian Restaurant': 'Food',
 'Burmese Restaurant': 'Food',
 'Cambodian Restaurant': 'Food',
 'Chinese Restaurant': 'Food',
 'Anhui Restaurant': 'Food',
 'Beijing Restaurant': 'Food',
 'Cantonese Restaurant': 'Food',
 'Cha Chaan Teng': 'Food',
 'Chinese Aristocrat Restaurant': 'Food',
 'Chinese Breakfast Place': 'Food',
 'Dim Sum Restaurant': 'Food',
 'Dongbei Restaurant': 'Food',
 'Fujian Restaurant': 'Food',
 'Guizhou Restaurant': 'Food',
 'Hainan Restaurant': 'Food',
 'Hakka Restaurant': 'Food',
 'Henan Restaurant': 'Food',
 'Hong Kong Restaurant': 'Food',
 'Huaiyang Restaurant': 'Food',
 'Hubei Restaurant': 'Food',
 'Hunan Restaurant': 'Food',
 'Imperial Restaurant': 'Food',
 'Jiangsu Restaurant': 'Food',
 'Jiangxi Restaurant': 'Food',
 'Macanese Restaurant': 'Food',
 'Manchu Restaurant': 'Food',
 'Peking Duck Restaurant': 'Food',
 'Shaanxi Restaurant': 'Food',
 'Shandong Restaurant': 'Food',
 'Shanghai Restaurant': 'Food',
 'Shanxi Restaurant': 'Food',
 'Szechuan Restaurant': 'Food',
 'Taiwanese Restaurant': 'Food',
 'Tianjin Restaurant': 'Food',
 'Xinjiang Restaurant': 'Food',
 'Yunnan Restaurant': 'Food',
 'Zhejiang Restaurant': 'Food',
 'Filipino Restaurant': 'Food',
 'Himalayan Restaurant': 'Food',
 'Hotpot Restaurant': 'Food',
 'Indonesian Restaurant': 'Food',
 'Acehnese Restaurant': 'Food',
 'Balinese Restaurant': 'Food',
 'Betawinese Restaurant': 'Food',
 'Indonesian Meatball Place': 'Food',
 'Javanese Restaurant': 'Food',
 'Manadonese Restaurant': 'Food',
 'Padangnese Restaurant': 'Food',
 'Sundanese Restaurant': 'Food',
 'Japanese Restaurant': 'Food',
 'Donburi Restaurant': 'Food',
 'Japanese Curry Restaurant': 'Food',
 'Kaiseki Restaurant': 'Food',
 'Kushikatsu Restaurant': 'Food',
 'Monjayaki Restaurant': 'Food',
 'Nabe Restaurant': 'Food',
 'Okonomiyaki Restaurant': 'Food',
 'Ramen Restaurant': 'Food',
 'Shabu-Shabu Restaurant': 'Food',
 'Soba Restaurant': 'Food',
 'Sukiyaki Restaurant': 'Food',
 'Sushi Restaurant': 'Food',
 'Takoyaki Place': 'Food',
 'Tempura Restaurant': 'Food',
 'Tonkatsu Restaurant': 'Food',
 'Udon Restaurant': 'Food',
 'Unagi Restaurant': 'Food',
 'Wagashi Place': 'Food',
 'Yakitori Restaurant': 'Food',
 'Yoshoku Restaurant': 'Food',
 'Korean Restaurant': 'Food',
 'Bossam/Jokbal Restaurant': 'Food',
 'Bunsik Restaurant': 'Food',
 'Gukbap Restaurant': 'Food',
 'Janguh Restaurant': 'Food',
 'Samgyetang Restaurant': 'Food',
 'Malay Restaurant': 'Food',
 'Mamak Restaurant': 'Food',
 'Mongolian Restaurant': 'Food',
 'Noodle House': 'Food',
 'Satay Restaurant': 'Food',
 'Thai Restaurant': 'Food',
 'Som Tum Restaurant': 'Food',
 'Tibetan Restaurant': 'Food',
 'Vietnamese Restaurant': 'Food',
 'Australian Restaurant': 'Food',
 'Austrian Restaurant': 'Food',
 'BBQ Joint': 'Food',
 'Bagel Shop': 'Food',
 'Bakery': 'Food',
 'Bangladeshi Restaurant': 'Food',
 'Belgian Restaurant': 'Food',
 'Bistro': 'Food',
 'Breakfast Spot': 'Food',
 'Bubble Tea Shop': 'Food',
 'Buffet': 'Food',
 'Burger Joint': 'Food',
 'Cafeteria': 'Food',
 'Café': 'Food',
 'Cajun / Creole Restaurant': 'Food',
 'Caribbean Restaurant': 'Food',
 'Cuban Restaurant': 'Food',
 'Caucasian Restaurant': 'Food',
 'Coffee Shop': 'Food',
 'Comfort Food Restaurant': 'Food',
 'Creperie': 'Food',
 'Czech Restaurant': 'Food',
 'Deli / Bodega': 'Food',
 'Dessert Shop': 'Food',
 'Cupcake Shop': 'Food',
 'Frozen Yogurt Shop': 'Food',
 'Ice Cream Shop': 'Food',
 'Pastry Shop': 'Food',
 'Pie Shop': 'Food',
 'Diner': 'Food',
 'Donut Shop': 'Food',
 'Dumpling Restaurant': 'Food',
 'Dutch Restaurant': 'Food',
 'Eastern European Restaurant': 'Food',
 'Belarusian Restaurant': 'Food',
 'Bosnian Restaurant': 'Food',
 'Bulgarian Restaurant': 'Food',
 'Romanian Restaurant': 'Food',
 'Tatar Restaurant': 'Food',
 'English Restaurant': 'Food',
 'Falafel Restaurant': 'Food',
 'Fast Food Restaurant': 'Food',
 'Fish & Chips Shop': 'Food',
 'Fondue Restaurant': 'Food',
 'Food Court': 'Food',
 'Food Stand': 'Food',
 'Food Truck': 'Food',
 'French Restaurant': 'Food',
 'Alsatian Restaurant': 'Food',
 'Auvergne Restaurant': 'Food',
 'Basque Restaurant': 'Food',
 'Brasserie': 'Food',
 'Breton Restaurant': 'Food',
 'Burgundian Restaurant': 'Food',
 'Catalan Restaurant': 'Food',
 "Ch'ti Restaurant": 'Food',
 'Corsican Restaurant': 'Food',
 'Estaminet': 'Food',
 'Labour Canteen': 'Food',
 'Lyonese Bouchon': 'Food',
 'Norman Restaurant': 'Food',
 'Provençal Restaurant': 'Food',
 'Savoyard Restaurant': 'Food',
 'Southwestern French Restaurant': 'Food',
 'Fried Chicken Joint': 'Food',
 'Friterie': 'Food',
 'Gastropub': 'Food',
 'German Restaurant': 'Food',
 'Apple Wine Pub': 'Food',
 'Bavarian Restaurant': 'Food',
 'Bratwurst Joint': 'Food',
 'Currywurst Joint': 'Food',
 'Franconian Restaurant': 'Food',
 'German Pop-Up Restaurant': 'Food',
 'Palatine Restaurant': 'Food',
 'Rhenisch Restaurant': 'Food',
 'Schnitzel Restaurant': 'Food',
 'Silesian Restaurant': 'Food',
 'Swabian Restaurant': 'Food',
 'Gluten-free Restaurant': 'Food',
 'Greek Restaurant': 'Food',
 'Bougatsa Shop': 'Food',
 'Cretan Restaurant': 'Food',
 'Fish Taverna': 'Food',
 'Grilled Meat Restaurant': 'Food',
 'Kafenio': 'Food',
 'Magirio': 'Food',
 'Meze Restaurant': 'Food',
 'Modern Greek Restaurant': 'Food',
 'Ouzeri': 'Food',
 'Patsa Restaurant': 'Food',
 'Souvlaki Shop': 'Food',
 'Taverna': 'Food',
 'Tsipouro Restaurant': 'Food',
 'Halal Restaurant': 'Food',
 'Hawaiian Restaurant': 'Food',
 'Poke Place': 'Food',
 'Hot Dog Joint': 'Food',
 'Hungarian Restaurant': 'Food',
 'Indian Restaurant': 'Food',
 'Andhra Restaurant': 'Food',
 'Awadhi Restaurant': 'Food',
 'Bengali Restaurant': 'Food',
 'Chaat Place': 'Food',
 'Chettinad Restaurant': 'Food',
 'Dhaba': 'Food',
 'Dosa Place': 'Food',
 'Goan Restaurant': 'Food',
 'Gujarati Restaurant': 'Food',
 'Hyderabadi Restaurant': 'Food',
 'Indian Chinese Restaurant': 'Food',
 'Indian Sweet Shop': 'Food',
 'Irani Cafe': 'Food',
 'Jain Restaurant': 'Food',
 'Karnataka Restaurant': 'Food',
 'Kerala Restaurant': 'Food',
 'Maharashtrian Restaurant': 'Food',
 'Mughlai Restaurant': 'Food',
 'Multicuisine Indian Restaurant': 'Food',
 'North Indian Restaurant': 'Food',
 'Northeast Indian Restaurant': 'Food',
 'Parsi Restaurant': 'Food',
 'Punjabi Restaurant': 'Food',
 'Rajasthani Restaurant': 'Food',
 'South Indian Restaurant': 'Food',
 'Udupi Restaurant': 'Food',
 'Irish Pub': 'Food',
 'Italian Restaurant': 'Food',
 'Abruzzo Restaurant': 'Food',
 'Agriturismo': 'Food',
 'Aosta Restaurant': 'Food',
 'Basilicata Restaurant': 'Food',
 'Calabria Restaurant': 'Food',
 'Campanian Restaurant': 'Food',
 'Emilia Restaurant': 'Food',
 'Friuli Restaurant': 'Food',
 'Ligurian Restaurant': 'Food',
 'Lombard Restaurant': 'Food',
 'Malga': 'Food',
 'Marche Restaurant': 'Food',
 'Molise Restaurant': 'Food',
 'Piadineria': 'Food',
 'Piedmontese Restaurant': 'Food',
 'Puglia Restaurant': 'Food',
 'Romagna Restaurant': 'Food',
 'Roman Restaurant': 'Food',
 'Sardinian Restaurant': 'Food',
 'Sicilian Restaurant': 'Food',
 'South Tyrolean Restaurant': 'Food',
 'Trattoria/Osteria': 'Food',
 'Trentino Restaurant': 'Food',
 'Tuscan Restaurant': 'Food',
 'Umbrian Restaurant': 'Food',
 'Veneto Restaurant': 'Food',
 'Jewish Restaurant': 'Food',
 'Kosher Restaurant': 'Food',
 'Juice Bar': 'Food',
 'Kebab Restaurant': 'Food',
 'Latin American Restaurant': 'Food',
 'Arepa Restaurant': 'Food',
 'Empanada Restaurant': 'Food',
 'Salvadoran Restaurant': 'Food',
 'South American Restaurant': 'Food',
 'Argentinian Restaurant': 'Food',
 'Brazilian Restaurant': 'Food',
 'Acai House': 'Food',
 'Baiano Restaurant': 'Food',
 'Central Brazilian Restaurant': 'Food',
 'Churrascaria': 'Food',
 'Empada House': 'Food',
 'Goiano Restaurant': 'Food',
 'Mineiro Restaurant': 'Food',
 'Northeastern Brazilian Restaurant': 'Food',
 'Northern Brazilian Restaurant': 'Food',
 'Pastelaria': 'Food',
 'Southeastern Brazilian Restaurant': 'Food',
 'Southern Brazilian Restaurant': 'Food',
 'Tapiocaria': 'Food',
 'Colombian Restaurant': 'Food',
 'Peruvian Restaurant': 'Food',
 'Venezuelan Restaurant': 'Food',
 'Mac & Cheese Joint': 'Food',
 'Mediterranean Restaurant': 'Food',
 'Moroccan Restaurant': 'Food',
 'Mexican Restaurant': 'Food',
 'Botanero': 'Food',
 'Burrito Place': 'Food',
 'Taco Place': 'Food',
 'Tex-Mex Restaurant': 'Food',
 'Yucatecan Restaurant': 'Food',
 'Middle Eastern Restaurant': 'Food',
 'Egyptian Restaurant': 'Food',
 'Iraqi Restaurant': 'Food',
 'Israeli Restaurant': 'Food',
 'Kurdish Restaurant': 'Food',
 'Lebanese Restaurant': 'Food',
 'Persian Restaurant': 'Food',
 'Ash and Haleem Place': 'Food',
 'Dizi Place': 'Food',
 'Gilaki Restaurant': 'Food',
 'Jegaraki': 'Food',
 'Tabbakhi': 'Food',
 'Shawarma Place': 'Food',
 'Syrian Restaurant': 'Food',
 'Yemeni Restaurant': 'Food',
 'Modern European Restaurant': 'Food',
 'Molecular Gastronomy Restaurant': 'Food',
 'Pakistani Restaurant': 'Food',
 'Pet Café': 'Food',
 'Pizza Place': 'Food',
 'Polish Restaurant': 'Food',
 'Portuguese Restaurant': 'Food',
 'Poutine Place': 'Food',
 'Restaurant': 'Food',
 'Russian Restaurant': 'Food',
 'Blini House': 'Food',
 'Pelmeni House': 'Food',
 'Salad Place': 'Food',
 'Sandwich Place': 'Food',
 'Scandinavian Restaurant': 'Food',
 'Scottish Restaurant': 'Food',
 'Seafood Restaurant': 'Food',
 'Slovak Restaurant': 'Food',
 'Snack Place': 'Food',
 'Soup Place': 'Food',
 'Southern / Soul Food Restaurant': 'Food',
 'Spanish Restaurant': 'Food',
 'Paella Restaurant': 'Food',
 'Tapas Restaurant': 'Food',
 'Sri Lankan Restaurant': 'Food',
 'Steakhouse': 'Food',
 'Swiss Restaurant': 'Food',
 'Tea Room': 'Food',
 'Theme Restaurant': 'Food',
 'Truck Stop': 'Food',
 'Turkish Restaurant': 'Food',
 'Borek Place': 'Food',
 'Cigkofte Place': 'Food',
 'Doner Restaurant': 'Food',
 'Gozleme Place': 'Food',
 'Kofte Place': 'Food',
 'Kokoreç Restaurant': 'Food',
 'Kumpir Restaurant': 'Food',
 'Kumru Restaurant': 'Food',
 'Manti Place': 'Food',
 'Meyhane': 'Food',
 'Pide Place': 'Food',
 'Pilavcı': 'Food',
 'Söğüş Place': 'Food',
 'Tantuni Restaurant': 'Food',
 'Turkish Coffeehouse': 'Food',
 'Turkish Home Cooking Restaurant': 'Food',
 'Çöp Şiş Place': 'Food',
 'Ukrainian Restaurant': 'Food',
 'Varenyky restaurant': 'Food',
 'West-Ukrainian Restaurant': 'Food',
 'Vegetarian / Vegan Restaurant': 'Food',
 'Wings Joint': 'Food',
 'Bar': 'Nightlife Spot',
 'Beach Bar': 'Nightlife Spot',
 'Beer Bar': 'Nightlife Spot',
 'Beer Garden': 'Nightlife Spot',
 'Champagne Bar': 'Nightlife Spot',
 'Cocktail Bar': 'Nightlife Spot',
 'Dive Bar': 'Nightlife Spot',
 'Gay Bar': 'Nightlife Spot',
 'Hookah Bar': 'Nightlife Spot',
 'Hotel Bar': 'Nightlife Spot',
 'Karaoke Bar': 'Nightlife Spot',
 'Pub': 'Nightlife Spot',
 'Sake Bar': 'Nightlife Spot',
 'Speakeasy': 'Nightlife Spot',
 'Sports Bar': 'Nightlife Spot',
 'Tiki Bar': 'Nightlife Spot',
 'Whisky Bar': 'Nightlife Spot',
 'Wine Bar': 'Nightlife Spot',
 'Brewery': 'Nightlife Spot',
 'Lounge': 'Nightlife Spot',
 'Night Market': 'Nightlife Spot',
 'Nightclub': 'Nightlife Spot',
 'Other Nightlife': 'Nightlife Spot',
 'Strip Club': 'Nightlife Spot',
 'Athletics & Sports': 'Outdoors & Recreation',
 'Badminton Court': 'Outdoors & Recreation',
 'Baseball Field': 'Outdoors & Recreation',
 'Basketball Court': 'Outdoors & Recreation',
 'Bowling Green': 'Outdoors & Recreation',
 'Curling Ice': 'Outdoors & Recreation',
 'Golf Course': 'Outdoors & Recreation',
 'Golf Driving Range': 'Outdoors & Recreation',
 'Gym / Fitness Center': 'Outdoors & Recreation',
 'Boxing Gym': 'Outdoors & Recreation',
 'Climbing Gym': 'Outdoors & Recreation',
 'Cycle Studio': 'Outdoors & Recreation',
 'Gym Pool': 'Outdoors & Recreation',
 'Gymnastics Gym': 'Outdoors & Recreation',
 'Gym': 'Outdoors & Recreation',
 'Martial Arts Dojo': 'Outdoors & Recreation',
 'Outdoor Gym': 'Outdoors & Recreation',
 'Pilates Studio': 'Outdoors & Recreation',
 'Track': 'Outdoors & Recreation',
 'Weight Loss Center': 'Outdoors & Recreation',
 'Yoga Studio': 'Outdoors & Recreation',
 'Hockey Field': 'Outdoors & Recreation',
 'Hockey Rink': 'Outdoors & Recreation',
 'Paintball Field': 'Outdoors & Recreation',
 'Rugby Pitch': 'Outdoors & Recreation',
 'Skate Park': 'Outdoors & Recreation',
 'Skating Rink': 'Outdoors & Recreation',
 'Soccer Field': 'Outdoors & Recreation',
 'Sports Club': 'Outdoors & Recreation',
 'Squash Court': 'Outdoors & Recreation',
 'Tennis Court': 'Outdoors & Recreation',
 'Volleyball Court': 'Outdoors & Recreation',
 'Bathing Area': 'Outdoors & Recreation',
 'Bay': 'Outdoors & Recreation',
 'Beach': 'Outdoors & Recreation',
 'Nudist Beach': 'Outdoors & Recreation',
 'Surf Spot': 'Outdoors & Recreation',
 'Bike Trail': 'Outdoors & Recreation',
 'Botanical Garden': 'Outdoors & Recreation',
 'Bridge': 'Outdoors & Recreation',
 'Campground': 'Outdoors & Recreation',
 'Canal Lock': 'Outdoors & Recreation',
 'Canal': 'Outdoors & Recreation',
 'Castle': 'Outdoors & Recreation',
 'Cave': 'Outdoors & Recreation',
 'Cemetery': 'Outdoors & Recreation',
 'Dive Spot': 'Outdoors & Recreation',
 'Dog Run': 'Outdoors & Recreation',
 'Farm': 'Outdoors & Recreation',
 'Field': 'Outdoors & Recreation',
 'Fishing Spot': 'Outdoors & Recreation',
 'Forest': 'Outdoors & Recreation',
 'Fountain': 'Outdoors & Recreation',
 'Garden': 'Outdoors & Recreation',
 'Gun Range': 'Outdoors & Recreation',
 'Harbor / Marina': 'Outdoors & Recreation',
 'Hill': 'Outdoors & Recreation',
 'Hot Spring': 'Outdoors & Recreation',
 'Indoor Play Area': 'Outdoors & Recreation',
 'Island': 'Outdoors & Recreation',
 'Lake': 'Outdoors & Recreation',
 'Lighthouse': 'Outdoors & Recreation',
 'Mountain Hut': 'Outdoors & Recreation',
 'Mountain': 'Outdoors & Recreation',
 'National Park': 'Outdoors & Recreation',
 'Nature Preserve': 'Outdoors & Recreation',
 'Other Great Outdoors': 'Outdoors & Recreation',
 'Palace': 'Outdoors & Recreation',
 'Park': 'Outdoors & Recreation',
 'Pedestrian Plaza': 'Outdoors & Recreation',
 'Playground': 'Outdoors & Recreation',
 'Plaza': 'Outdoors & Recreation',
 'Pool': 'Outdoors & Recreation',
 'Rafting': 'Outdoors & Recreation',
 'Recreation Center': 'Outdoors & Recreation',
 'Reservoir': 'Outdoors & Recreation',
 'River': 'Outdoors & Recreation',
 'Rock Climbing Spot': 'Outdoors & Recreation',
 'Roof Deck': 'Outdoors & Recreation',
 'Scenic Lookout': 'Outdoors & Recreation',
 'Sculpture Garden': 'Outdoors & Recreation',
 'Ski Area': 'Outdoors & Recreation',
 'Apres Ski Bar': 'Outdoors & Recreation',
 'Ski Chairlift': 'Outdoors & Recreation',
 'Ski Chalet': 'Outdoors & Recreation',
 'Ski Lodge': 'Outdoors & Recreation',
 'Ski Trail': 'Outdoors & Recreation',
 'Skydiving Drop Zone': 'Outdoors & Recreation',
 'Stables': 'Outdoors & Recreation',
 'State / Provincial Park': 'Outdoors & Recreation',
 'States & Municipalities': 'Outdoors & Recreation',
 'City': 'Outdoors & Recreation',
 'County': 'Outdoors & Recreation',
 'Country': 'Outdoors & Recreation',
 'Neighborhood': 'Outdoors & Recreation',
 'State': 'Outdoors & Recreation',
 'Town': 'Outdoors & Recreation',
 'Village': 'Outdoors & Recreation',
 'Summer Camp': 'Outdoors & Recreation',
 'Trail': 'Outdoors & Recreation',
 'Tree': 'Outdoors & Recreation',
 'Vineyard': 'Outdoors & Recreation',
 'Volcano': 'Outdoors & Recreation',
 'Waterfall': 'Outdoors & Recreation',
 'Waterfront': 'Outdoors & Recreation',
 'Well': 'Outdoors & Recreation',
 'Windmill': 'Outdoors & Recreation',
 'Animal Shelter': 'Professional & Other Places',
 'Art Studio': 'Professional & Other Places',
 'Auditorium': 'Professional & Other Places',
 'Ballroom': 'Professional & Other Places',
 'Building': 'Professional & Other Places',
 'Business Center': 'Professional & Other Places',
 'Cidery': 'Professional & Other Places',
 'Club House': 'Professional & Other Places',
 'Community Center': 'Professional & Other Places',
 'Convention Center': 'Professional & Other Places',
 'Meeting Room': 'Professional & Other Places',
 'Cultural Center': 'Professional & Other Places',
 'Distillery': 'Professional & Other Places',
 'Distribution Center': 'Professional & Other Places',
 'Event Space': 'Professional & Other Places',
 'Outdoor Event Space': 'Professional & Other Places',
 'Factory': 'Professional & Other Places',
 'Fair': 'Professional & Other Places',
 'Funeral Home': 'Professional & Other Places',
 'Government Building': 'Professional & Other Places',
 'Capitol Building': 'Professional & Other Places',
 'City Hall': 'Professional & Other Places',
 'Courthouse': 'Professional & Other Places',
 'Embassy / Consulate': 'Professional & Other Places',
 'Fire Station': 'Professional & Other Places',
 'Monument / Landmark': 'Professional & Other Places',
 'Police Station': 'Professional & Other Places',
 'Town Hall': 'Professional & Other Places',
 'Industrial Estate': 'Professional & Other Places',
 'Laboratory': 'Professional & Other Places',
 'Library': 'Professional & Other Places',
 'Meadery': 'Professional & Other Places',
 'Medical Center': 'Professional & Other Places',
 'Acupuncturist': 'Professional & Other Places',
 'Alternative Healer': 'Professional & Other Places',
 'Chiropractor': 'Professional & Other Places',
 "Dentist's Office": 'Professional & Other Places',
 "Doctor's Office": 'Professional & Other Places',
 'Emergency Room': 'Professional & Other Places',
 'Eye Doctor': 'Professional & Other Places',
 'Hospital': 'Professional & Other Places',
 'Hospital Ward': 'Professional & Other Places',
 'Maternity Clinic': 'Professional & Other Places',
 'Medical Lab': 'Professional & Other Places',
 'Mental Health Office': 'Professional & Other Places',
 'Nutritionist': 'Professional & Other Places',
 'Physical Therapist': 'Professional & Other Places',
 'Rehab Center': 'Professional & Other Places',
 'Urgent Care Center': 'Professional & Other Places',
 'Veterinarian': 'Professional & Other Places',
 'Military Base': 'Professional & Other Places',
 'Non-Profit': 'Professional & Other Places',
 'Observatory': 'Professional & Other Places',
 'Office': 'Professional & Other Places',
 'Advertising Agency': 'Professional & Other Places',
 'Campaign Office': 'Professional & Other Places',
 'Conference Room': 'Professional & Other Places',
 'Corporate Amenity': 'Professional & Other Places',
 'Corporate Cafeteria': 'Professional & Other Places',
 'Corporate Coffee Shop': 'Professional & Other Places',
 'Coworking Space': 'Professional & Other Places',
 'Tech Startup': 'Professional & Other Places',
 'Parking': 'Professional & Other Places',
 'Post Office': 'Professional & Other Places',
 'Power Plant': 'Professional & Other Places',
 'Prison': 'Professional & Other Places',
 'Radio Station': 'Professional & Other Places',
 'Recruiting Agency': 'Professional & Other Places',
 'Research Station': 'Professional & Other Places',
 'School': 'Professional & Other Places',
 'Adult Education Center': 'Professional & Other Places',
 'Circus School': 'Professional & Other Places',
 'Cooking School': 'Professional & Other Places',
 'Driving School': 'Professional & Other Places',
 'Elementary School': 'Professional & Other Places',
 'Flight School': 'Professional & Other Places',
 'High School': 'Professional & Other Places',
 'Language School': 'Professional & Other Places',
 'Middle School': 'Professional & Other Places',
 'Music School': 'Professional & Other Places',
 'Nursery School': 'Professional & Other Places',
 'Preschool': 'Professional & Other Places',
 'Private School': 'Professional & Other Places',
 'Religious School': 'Professional & Other Places',
 'Swim School': 'Professional & Other Places',
 'Social Club': 'Professional & Other Places',
 'Spiritual Center': 'Professional & Other Places',
 'Buddhist Temple': 'Professional & Other Places',
 'Cemevi': 'Professional & Other Places',
 'Church': 'Professional & Other Places',
 'Confucian Temple': 'Professional & Other Places',
 'Hindu Temple': 'Professional & Other Places',
 'Kingdom Hall': 'Professional & Other Places',
 'Monastery': 'Professional & Other Places',
 'Mosque': 'Professional & Other Places',
 'Prayer Room': 'Professional & Other Places',
 'Shrine': 'Professional & Other Places',
 'Sikh Temple': 'Professional & Other Places',
 'Synagogue': 'Professional & Other Places',
 'Temple': 'Professional & Other Places',
 'Terreiro': 'Professional & Other Places',
 'TV Station': 'Professional & Other Places',
 'Voting Booth': 'Professional & Other Places',
 'Warehouse': 'Professional & Other Places',
 'Waste Facility': 'Professional & Other Places',
 'Wedding Hall': 'Professional & Other Places',
 'Winery': 'Professional & Other Places',
 'Assisted Living': 'Residence',
 'Home (private)': 'Residence',
 'Housing Development': 'Residence',
 'Residential Building (Apartment / Condo)': 'Residence',
 'Trailer Park': 'Residence',
 'ATM': 'Shop & Service',
 'Adult Boutique': 'Shop & Service',
 'Antique Shop': 'Shop & Service',
 'Arts & Crafts Store': 'Shop & Service',
 'Astrologer': 'Shop & Service',
 'Auto Dealership': 'Shop & Service',
 'New Auto Dealership': 'Shop & Service',
 'Used Auto Dealership': 'Shop & Service',
 'Auto Garage': 'Shop & Service',
 'Auto Workshop': 'Shop & Service',
 'Automotive Shop': 'Shop & Service',
 'Baby Store': 'Shop & Service',
 'Bank': 'Shop & Service',
 'Bath House': 'Shop & Service',
 'Batik Shop': 'Shop & Service',
 'Betting Shop': 'Shop & Service',
 'Big Box Store': 'Shop & Service',
 'Bike Shop': 'Shop & Service',
 'Board Shop': 'Shop & Service',
 'Bookstore': 'Shop & Service',
 'Bridal Shop': 'Shop & Service',
 'Business Service': 'Shop & Service',
 'Camera Store': 'Shop & Service',
 'Candy Store': 'Shop & Service',
 'Car Wash': 'Shop & Service',
 'Carpet Store': 'Shop & Service',
 'Check Cashing Service': 'Shop & Service',
 'Child Care Service': 'Shop & Service',
 'Daycare': 'Shop & Service',
 'Chocolate Shop': 'Shop & Service',
 'Clothing Store': 'Shop & Service',
 'Accessories Store': 'Shop & Service',
 'Boutique': 'Shop & Service',
 'Kids Store': 'Shop & Service',
 'Lingerie Store': 'Shop & Service',
 "Men's Store": 'Shop & Service',
 'Shoe Store': 'Shop & Service',
 "Women's Store": 'Shop & Service',
 'Comic Shop': 'Shop & Service',
 'Construction & Landscaping': 'Shop & Service',
 'Convenience Store': 'Shop & Service',
 'Cosmetics Shop': 'Shop & Service',
 'Costume Shop': 'Shop & Service',
 'Credit Union': 'Shop & Service',
 'Currency Exchange': 'Shop & Service',
 'Department Store': 'Shop & Service',
 'Design Studio': 'Shop & Service',
 'Discount Store': 'Shop & Service',
 'Dive Shop': 'Shop & Service',
 'Drugstore': 'Shop & Service',
 'Dry Cleaner': 'Shop & Service',
 'EV Charging Station': 'Shop & Service',
 'Electronics Store': 'Shop & Service',
 'Entertainment Service': 'Shop & Service',
 'Event Service': 'Shop & Service',
 'Fabric Shop': 'Shop & Service',
 'Film Studio': 'Shop & Service',
 'Financial or Legal Service': 'Shop & Service',
 'Fireworks Store': 'Shop & Service',
 'Fishing Store': 'Shop & Service',
 'Flea Market': 'Shop & Service',
 'Floating Market': 'Shop & Service',
 'Flower Shop': 'Shop & Service',
 'Food & Drink Shop': 'Shop & Service',
 'Beer Store': 'Shop & Service',
 'Butcher': 'Shop & Service',
 'Cheese Shop': 'Shop & Service',
 'Coffee Roaster': 'Shop & Service',
 'Dairy Store': 'Shop & Service',
 'Farmers Market': 'Shop & Service',
 'Fish Market': 'Shop & Service',
 'Food Service': 'Shop & Service',
 'Gourmet Shop': 'Shop & Service',
 'Grocery Store': 'Shop & Service',
 'Health Food Store': 'Shop & Service',
 'Kuruyemişçi': 'Shop & Service',
 'Liquor Store': 'Shop & Service',
 'Organic Grocery': 'Shop & Service',
 'Sausage Shop': 'Shop & Service',
 'Street Food Gathering': 'Shop & Service',
 'Supermarket': 'Shop & Service',
 'Turşucu': 'Shop & Service',
 'Wine Shop': 'Shop & Service',
 'Frame Store': 'Shop & Service',
 'Fruit & Vegetable Store': 'Shop & Service',
 'Furniture / Home Store': 'Shop & Service',
 'Lighting Store': 'Shop & Service',
 'Gaming Cafe': 'Shop & Service',
 'Garden Center': 'Shop & Service',
 'Gas Station': 'Shop & Service',
 'Gift Shop': 'Shop & Service',
 'Gun Shop': 'Shop & Service',
 'Hardware Store': 'Shop & Service',
 'Health & Beauty Service': 'Shop & Service',
 'Herbs & Spices Store': 'Shop & Service',
 'Hobby Shop': 'Shop & Service',
 'Home Service': 'Shop & Service',
 'Hunting Supply': 'Shop & Service',
 'IT Services': 'Shop & Service',
 'Insurance Office': 'Shop & Service',
 'Internet Cafe': 'Shop & Service',
 'Jewelry Store': 'Shop & Service',
 'Kitchen Supply Store': 'Shop & Service',
 'Knitting Store': 'Shop & Service',
 'Laundromat': 'Shop & Service',
 'Laundry Service': 'Shop & Service',
 'Lawyer': 'Shop & Service',
 'Leather Goods Store': 'Shop & Service',
 'Locksmith': 'Shop & Service',
 'Lottery Retailer': 'Shop & Service',
 'Luggage Store': 'Shop & Service',
 'Marijuana Dispensary': 'Shop & Service',
 'Market': 'Shop & Service',
 'Massage Studio': 'Shop & Service',
 'Mattress Store': 'Shop & Service',
 'Medical Supply Store': 'Shop & Service',
 'Miscellaneous Shop': 'Shop & Service',
 'Mobile Phone Shop': 'Shop & Service',
 'Mobility Store': 'Shop & Service',
 'Motorcycle Shop': 'Shop & Service',
 'Motorsports Shop': 'Shop & Service',
 'Music Store': 'Shop & Service',
 'Nail Salon': 'Shop & Service',
 'Newsstand': 'Shop & Service',
 'Notary': 'Shop & Service',
 'Optical Shop': 'Shop & Service',
 'Other Repair Shop': 'Shop & Service',
 'Outdoor Supply Store': 'Shop & Service',
 'Outlet Mall': 'Shop & Service',
 'Outlet Store': 'Shop & Service',
 'Paper / Office Supplies Store': 'Shop & Service',
 'Pawn Shop': 'Shop & Service',
 'Perfume Shop': 'Shop & Service',
 'Pet Service': 'Shop & Service',
 'Pet Store': 'Shop & Service',
 'Pharmacy': 'Shop & Service',
 'Photography Lab': 'Shop & Service',
 'Photography Studio': 'Shop & Service',
 'Piercing Parlor': 'Shop & Service',
 'Pop-Up Shop': 'Shop & Service',
 'Print Shop': 'Shop & Service',
 'Public Bathroom': 'Shop & Service',
 'Real Estate Office': 'Shop & Service',
 'Record Shop': 'Shop & Service',
 'Recording Studio': 'Shop & Service',
 'Recycling Facility': 'Shop & Service',
 'Rental Service': 'Shop & Service',
 'Salon / Barbershop': 'Shop & Service',
 'Sauna / Steam Room': 'Shop & Service',
 'Shipping Store': 'Shop & Service',
 'Shoe Repair': 'Shop & Service',
 'Shopping Mall': 'Shop & Service',
 'Shopping Plaza': 'Shop & Service',
 'Skate Shop': 'Shop & Service',
 'Ski Shop': 'Shop & Service',
 'Smoke Shop': 'Shop & Service',
 'Smoothie Shop': 'Shop & Service',
 'Souvenir Shop': 'Shop & Service',
 'Spa': 'Shop & Service',
 'Sporting Goods Shop': 'Shop & Service',
 'Stationery Store': 'Shop & Service',
 'Storage Facility': 'Shop & Service',
 'Supplement Shop': 'Shop & Service',
 'Tailor Shop': 'Shop & Service',
 'Tanning Salon': 'Shop & Service',
 'Tattoo Parlor': 'Shop & Service',
 'Thrift / Vintage Store': 'Shop & Service',
 'Toy / Game Store': 'Shop & Service',
 'Travel Agency': 'Shop & Service',
 'Used Bookstore': 'Shop & Service',
 'Vape Store': 'Shop & Service',
 'Video Game Store': 'Shop & Service',
 'Video Store': 'Shop & Service',
 'Warehouse Store': 'Shop & Service',
 'Watch Shop': 'Shop & Service',
 'Airport': 'Travel & Transport',
 'Airport Food Court': 'Travel & Transport',
 'Airport Gate': 'Travel & Transport',
 'Airport Lounge': 'Travel & Transport',
 'Airport Service': 'Travel & Transport',
 'Airport Terminal': 'Travel & Transport',
 'Airport Tram': 'Travel & Transport',
 'Baggage Claim': 'Travel & Transport',
 'Plane': 'Travel & Transport',
 'Baggage Locker': 'Travel & Transport',
 'Bike Rental / Bike Share': 'Travel & Transport',
 'Boat Rental': 'Travel & Transport',
 'Boat or Ferry': 'Travel & Transport',
 'Border Crossing': 'Travel & Transport',
 'Bus Station': 'Travel & Transport',
 'Bus Line': 'Travel & Transport',
 'Bus Stop': 'Travel & Transport',
 'Cable Car': 'Travel & Transport',
 'Cruise': 'Travel & Transport',
 'Duty-free Shop': 'Travel & Transport',
 'General Travel': 'Travel & Transport',
 'Heliport': 'Travel & Transport',
 'Hotel': 'Travel & Transport',
 'Bed & Breakfast': 'Travel & Transport',
 'Boarding House': 'Travel & Transport',
 'Hostel': 'Travel & Transport',
 'Hotel Pool': 'Travel & Transport',
 'Inn': 'Travel & Transport',
 'Motel': 'Travel & Transport',
 'Resort': 'Travel & Transport',
 'Vacation Rental': 'Travel & Transport',
 'Intersection': 'Travel & Transport',
 'Light Rail Station': 'Travel & Transport',
 'Metro Station': 'Travel & Transport',
 'Moving Target': 'Travel & Transport',
 'Pier': 'Travel & Transport',
 'Port': 'Travel & Transport',
 'RV Park': 'Travel & Transport',
 'Rental Car Location': 'Travel & Transport',
 'Rest Area': 'Travel & Transport',
 'Road': 'Travel & Transport',
 'Taxi Stand': 'Travel & Transport',
 'Taxi': 'Travel & Transport',
 'Toll Booth': 'Travel & Transport',
 'Toll Plaza': 'Travel & Transport',
 'Tourist Information Center': 'Travel & Transport',
 'Train Station': 'Travel & Transport',
 'Platform': 'Travel & Transport',
 'Train': 'Travel & Transport',
 'Tram Station': 'Travel & Transport',
 'Transportation Service': 'Travel & Transport',
 'Travel Lounge': 'Travel & Transport',
 'Tunnel': 'Travel & Transport'}
In [58]:
all_categories["parent_category"]=all_categories["category"].apply(lambda c:category_mapping.get(c,"na"))
pivot=pd.pivot_table(all_categories,
               values='count', 
               index=['parent_category'],
               columns=['institution'],
               aggfunc=np.sum, 
               fill_value=0)
pivot
Out[58]:
institution Bank of America N.A. GA1-006-15-40 Citizens Bank Community Bank, N.A. Five Star Bank JPMorgan Chase Bank, National Association Key Bank, National Association Manufacturers and Traders Trust Company NBT Bank, National Association TD Bank N.A. Trustco Bank N.A. CTF
parent_category
Arts & Entertainment 8 0 4 1 2 5 6 4 5 4
Food 64 37 42 26 104 72 35 65 109 44
Nightlife Spot 9 3 12 3 8 16 5 9 10 3
Outdoors & Recreation 13 3 8 4 8 5 6 3 12 2
Professional & Other Places 2 0 1 2 2 0 0 0 2 0
Residence 0 0 0 0 0 1 0 0 1 0
Shop & Service 30 66 24 45 45 51 43 44 45 27
Travel & Transport 9 2 6 2 3 6 5 2 9 3
na 0 0 0 0 0 0 0 0 0 1
In [59]:
from matplotlib import pyplot
import seaborn
a4_dims = (11.7, 8.27)
fig, ax = pyplot.subplots(figsize=a4_dims)
sns.heatmap(ax=ax, data=pivot, cmap="YlGnBu")
Out[59]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f7f6f680dd0>
  • Reducing the dimension of categories makes our data more readable
  • Venues in category "Food" and "Shop & Service" are the most common in the neighbourhood of ATMs.
  • Unfortunately we cannot identify any "institution specific pattern" using that heatmap

Next steps:

  • Given our last observations running a clustering algorithm on foursquare data is unlikely to provide us with meaningfull insights.
  • Further effort should be put in improving our data collection and data cleanup
  • We need to experiment with new sources to identify more potentially meaningfull features.